package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.ExchangeConstants.ITEM_EXCHANGE_NAME;

@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {
    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private SpuDetailService spuDetailService;
    @Autowired
    private AmqpTemplate amqpTemplate;

//    商品分页查询
    @Override
    public PageDTO<SpuDTO> querySpuByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
//        健壮性
        int current = Math.max(page, 1);
        int size = Math.max(rows, 5);
        // 2.准备查询条件， SELECT * FROM tb_spu WHERE saleable = ? AND category_id = ? AND brand_id = ? AND id = ?
        IPage<Spu> result = query().eq(saleable != null, "saleable", saleable)
                .eq(categoryId != null, "category_id", categoryId)
                .eq(brandId != null, "brand_id", brandId)
                .eq(id != null, "id", id)
                .page(new Page<>(current, size));
//        解析查询结果

        long total = result.getTotal();
        long pages = result.getPages();
        List<Spu> list = result.getRecords();
//        vo转为DTO
        List<SpuDTO> dtoList = SpuDTO.convertEntityList(list);
        for (SpuDTO spuDTO : dtoList) {
            // 准备商品分类和品牌名称
            handleCategoryAndBrandName(spuDTO);
        }

        return new PageDTO<>(total, pages, dtoList);
        

    }

    //        准备商品分类和品牌名称
    private void handleCategoryAndBrandName(SpuDTO spuDTO) {
//        根据品牌id擦好像品牌名称
        Brand brand = brandService.getById(spuDTO.getBrandId());
//        把不为空值的品牌名称值传给spuDTO
        if(brand != null){
            spuDTO.setBrandName(brand.getName());
        }
//        根据三级分类id查询分类集合
        Collection<Category> categories = categoryService.listByIds(spuDTO.getCategoryIds());
        if(!CollectionUtils.isEmpty(categories)){
//            取出分类的名称，拼接连级查询
            String names = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);

        }

    }
//新增商品
    @Transactional
    @Override
    public void saveGoods(SpuDTO spuDTO) {
//        新增Spu
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        boolean result = save(spu);
        if(!result){
            throw new LyException(500, "新增商品失败");
        }
//        新增SpuDetail
        List<Sku> list = spuDTO.getSkus().stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
//            默认商品是下架
            sku.setSaleable(false);
//            新增回显id信息
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());
//        批量新增
        skuService.saveBatch(list);
    }
    //修改商品上下架
    @Transactional
    @Override
    public void updateSabeable(Long id, Boolean saleable) {
//更新Spu
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        boolean result = updateById(spu);
        if(!result){
            throw new LyException(500, "更新失败");
        }
//        更新Sku是否下架字段
        boolean success = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!success){
            throw new LyException(500, "更新失败");
        }
//        发送MQ消息
        String routingKey = saleable ? MQConstants.RoutingKeyConstants.ITEM_UP_KEY : MQConstants.RoutingKeyConstants.ITEM_DOWN_KEY;
        amqpTemplate.convertAndSend(ITEM_EXCHANGE_NAME, routingKey, id);

    }
//    根据id查询spu及sku、spuDetail等

    @Override
    public SpuDTO queryGoodsById(Long id) {
        //        查询spu
        Spu spu = getById(id);
        if(spu == null){
            throw new LyException(400, "商品的id不存在");
        }
//        数据转为DTO
        SpuDTO spuDTO = new SpuDTO(spu);
//        查询商品详情
        SpuDetail detail = spuDetailService.getById(id);
        if(detail == null){
            throw new LyException(400, "商品id不存在");
        }
        spuDTO.setSpuDetail(new SpuDetailDTO(detail));
//        查询sku
        List<Sku> skuList = skuService.query().eq("spu_id", id).list();
        if(CollectionUtils.isEmpty(skuList)){
            throw new LyException(400, "商品id不存在");
        }
        spuDTO.setSkus(SkuDTO.convertEntityList(skuList));
//        准备商品分类和品牌名称
        handleCategoryAndBrandName(spuDTO);
        return spuDTO;
    }

    //    更新商品
    @Transactional
    @Override
    public void updateGoods(SpuDTO spuDTO) {
//    修改spu
//        判断是否存在spu的id,存在则需要修改，不存在则不用修改
        Long spuId = spuDTO.getId();
        if(spuId != null){
//            spu需要修改，更新spu 转为DTO
            Spu spu = spuDTO.toEntity(Spu.class);
//            禁止修改savleable
            spu.setSaleable(null);
//            更新spu
            boolean success = updateById(spu);
            if(!success){
                throw new LyException(500, "更新失败");
            }


//        修改Detail
            SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
//            判断是否存在
            if (spuDetail != null && spuDetail.getSpuId() != null){
//                spudetail存在需要修改，转为DTO
                SpuDetail detail = spuDetail.toEntity(SpuDetail.class);
//                更新spuDetail表中的数据
                boolean result = spuDetailService.updateById(detail);
                if (!result){
                    throw new LyException(500, "更新商品失败！");
                }
            }
//            修改sku
            List<SkuDTO> dtoList = spuDTO.getSkus();
//            判断是否包含sku
            if (CollectionUtils.isEmpty(dtoList)){
//                没有sku，无需处理
                return;
            }
//            转换DTO,并将sku根据saleable是否为null来分组,null 是更新或修改，不是null是删除
            Map<Boolean, List<Sku>> map = dtoList.stream()
//                    先转为DTO
                    .map(skuDTO -> skuDTO.toEntity(Sku.class))
//                    再判断，对集合进行分组，分组的依据是否包含saleable，包含则是删除操作，不包含则为增加或修改
                    .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));
//            获取要更新或要修改的sku
            List<Sku> insertOrUpdateList = map.get(true);
//            如果不为空，则修改或新增
            if (!CollectionUtils.isEmpty(insertOrUpdateList)){
                skuService.saveOrUpdateBatch(insertOrUpdateList);
            }
//            获取要删除的sku
            List<Sku> deleteSkuList = map.get(false);
            if(!CollectionUtils.isEmpty(deleteSkuList)){
//                存在要删除的sku
                List<Long> idlist = deleteSkuList.stream().map(Sku::getId).collect(Collectors.toList());
                //删除
                skuService.removeByIds(idlist);
            }
        }
    }
}
